﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Globalization;
using System.IO;

namespace MediaLibraryManager
{
	/// <summary>
	/// Implements a <see cref="TextWriter"/> for writing information to the debugger log.
	/// Code taken from http://www.u2u.info/Blogs/Kris/Lists/Posts/Post.aspx?ID=11 by Kris Vandermotten.
	/// </summary>
	/// <seealso cref="Debugger.Log"/>
	public class DebuggerWriter : TextWriter
	{
		private bool isOpen;
		private static UnicodeEncoding encoding;
		private readonly int level;
		private readonly string category;

		/// <summary>
		/// Initializes a new instance of the <see cref="DebuggerWriter"/> class.
		/// </summary>
		public DebuggerWriter()
			: this(0,Debugger.DefaultCategory)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="DebuggerWriter"/> class with the specified level and category.
		/// </summary>
		/// <param name="level">A description of the importance of the messages.</param>
		/// <param name="category">The category of the messages.</param>
		public DebuggerWriter(int level,string category)
			: this(level,category,CultureInfo.CurrentCulture)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="DebuggerWriter"/> class with the specified level, category and format provider.
		/// </summary>
		/// <param name="level">A description of the importance of the messages.</param>
		/// <param name="category">The category of the messages.</param>
		/// <param name="formatProvider">An <see cref="IFormatProvider"/> object that controls formatting.</param>
		public DebuggerWriter(int level,string category,IFormatProvider formatProvider)
			: base(formatProvider)
		{
			this.level = level;
			this.category = category;
			this.isOpen = true;
		}

		protected override void Dispose(bool disposing)
		{
			isOpen = false;
			base.Dispose(disposing);
		}

		public override void Write(char value)
		{
			if (!isOpen)
			{
				throw new ObjectDisposedException(null);
			}
			Debugger.Log(level,category,value.ToString());
		}

		public override void Write(string value)
		{
			if (!isOpen)
			{
				throw new ObjectDisposedException(null);
			}
			if (value != null)
			{
				Debugger.Log(level,category,value);
			}
		}

		public override void Write(char[] buffer,int index,int count)
		{
			if (!isOpen)
			{
				throw new ObjectDisposedException(null);
			}
			if (buffer == null || index < 0 || count < 0 || buffer.Length - index < count)
			{
				base.Write(buffer,index,count); // delegate throw exception to base class
			}
			Debugger.Log(level,category,new string(buffer,index,count));
		}

		public override Encoding Encoding
		{
			get
			{
				if (encoding == null)
				{
					encoding = new UnicodeEncoding(false,false);
				}
				return encoding;
			}
		}

		public int Level
		{
			get { return level; }
		}

		public string Category
		{
			get { return category; }
		}
	}

}
